package com.lemon.stock.util

import com.lemon.stock.app.StockApplication
import com.lemon.stock.dao.BonusDao
import com.lemon.stock.dao.TradeDao
import com.lemon.stock.entity.Batch
import com.lemon.stock.entity.Bonus
import com.lemon.stock.entity.Stock
import com.lemon.stock.entity.Trade
import kotlin.math.roundToInt

/**
 * 股票根据代码判断所属交易所
 * 返回交易所和股票代码的综合代码
 * @param id 股票代码6位
 *
 */
fun sysStockExchange(id: String): String{
    if(id.length !=6 ){
        return ""
    }
    val pre2 = id.substring(0, 2)
    var exchange = when(pre2){
        "00"->"sz"
        "30"->"sz"
        "60"->"sh"
        "68"->"sh"
        "15"->"sz"
        "51"->"sh"
        "58"->"sh"
        else -> ""
    }
    return exchange+id
}

/**
 * 股票实时收益
 * @param stock 股票类
 *
 */
fun sysStockMotion(stock: Stock){
    stock.worthMoney = stock.stockPrice*stock.holdStock
    stock.profitMoney = stock.worthMoney + stock.bonusMoney - stock.investMoney - stock.commissionMoney - stock.transferMoney - stock.taxMoney
    if(stock.investMoney>0){
        stock.profitRatio = (stock.profitMoney*10000/stock.investMoney).roundToInt().toFloat()/100
    }else if(stock.holdStock>0){
        stock.profitRatio = 100F
    }else{
        stock.profitRatio = 0F
    }
}

/**
 * 汇集股票（单个）数据
 * 根据购买记录汇总股票的各项数据
 * @param stock 股票类
 *
 */
fun sysStockGather(stock: Stock){
    val tradeDao = StockApplication.getDataRoom().tradeDao()

    val trades = tradeDao.stockTrades(id = stock.stockId, index = stock.investIndex)
    var holdStock = 0
    var investMoney = 0f
    var bonusMoney = 0f
    var costMoney = 0f
    var commission = 0f
    var transfer = 0f
    var tax = 0f

    for(trade in trades){
        if(trade.status == 8){
            holdStock += trade.stockAmount
            investMoney += trade.stockAmount * trade.buyPrice
        }
        commission += trade.commissionMoney
        transfer += trade.transferMoney
        tax += trade.taxMoney
        bonusMoney += trade.bonusMoney
        //btax += trade.bonusTax
        costMoney += (trade.buyPrice - trade.sellPrice)*trade.stockAmount
    }

    stock.holdStock = holdStock
    stock.investMoney = investMoney
    stock.bonusMoney = bonusMoney
    stock.commissionMoney = commission
    stock.transferMoney = transfer
    stock.taxMoney = tax

    if(stock.holdStock>stock.maxAmount){
        stock.maxAmount = stock.holdStock
    }
    if(stock.investMoney>stock.maxInvest){
        stock.maxInvest = stock.investMoney
    }

    if(stock.holdStock>0){
        costMoney += commission + transfer + tax + stock.bonusTax
        stock.costPrice = (costMoney * 100/stock.holdStock).roundToInt().toFloat()/100
    }else{
        stock.investProfit = stock.bonusMoney  - costMoney  - commission - transfer - tax - stock.bonusTax
    }

    sysStockMotion(stock)
}

/**
 * 预估红利税
 * 红利逻辑并不严谨，此处只考虑了一次分红的情况，未考虑两次分红在1年以内的情况
 * @param stock 股票类
 * @param amount 卖出数量
 * @param date 卖出日期，时间戳（毫秒）
 *
 */
fun sysPredictBonusTax(stock: Stock, amount: Int, date: Long): Float{
    var bonusTax = 0f
    val tradeDao = StockApplication.getDataRoom().tradeDao()
    var liTrade = tradeDao.holdTrades(stockId = stock.stockId)

    var round = amount
    var index = 0
    while (round > 0) {
        var trade = liTrade[index]
        var bonusMoney = when{
            round < trade.stockAmount -> trade.bonusMoney*round/trade.stockAmount
            else  -> trade.bonusMoney
        }

        if(trade.bonusId>0){
            var faxRatio = bonusTaxRatio(trade.buyDate, date)
            if(faxRatio>0){
                bonusTax += (bonusMoney * faxRatio * 100).roundToInt().toFloat()/100
            }
        }
        round -= trade.stockAmount
        index ++
    }
    return bonusTax
}

/**
 * 证券买入
 * @param stock 股票类
 * @param price 买入单价
 * @param amount 买入数量
 * @param date 买入日期，时间戳（毫秒）
 * @param commission 手续费
 * @param transfer 过户费
 *
 */
fun sysStockBuy(stock: Stock, price: Float, amount: Int, date: Long, commission: Float, transfer: Float ): Trade{
    if(stock.status != 6){
        stock.status = 6
        stock.investIndex++
    }

    var trade = Trade(stockId=stock.stockId, investIndex = stock.investIndex, stockAmount = amount,
        buyDate = date, buyPrice = price, commissionMoney = commission, transferMoney = transfer)

    stock.totalAmount += amount
    stock.totalInvest += price* amount
    stock.buyLine = (price*90).toInt().toFloat()/100
    stock.sellLine = (price*115).toInt().toFloat()/100

    if(stock.firstBuy < 1 ){
        stock.firstBuy = date
    }
    return trade
}

/**
 * 证券卖出
 * @param tradeDao 购买记录的数据库访问类
 * @param stock 股票类
 * @param price 卖出单价
 * @param amount 卖出数量
 * @param date 卖出日期，时间戳（毫秒）
 * @param commission 手续费
 * @param transfer 过户费
 * @param tax 印花税
 */
fun sysStockSell(tradeDao: TradeDao, stock: Stock, price: Float, amount: Int, date: Long, commission: Float, transfer: Float, tax: Float)
        : Pair<Trade?, MutableList<Trade>>{
    var split: Trade? = null
    var saveTrade: MutableList<Trade> = mutableListOf()
    var liTrade = tradeDao.holdTrades(stockId = stock.stockId)

    var index = 0
    var round = amount
    var sumCommission = 0f
    var sumTransfer = 0f
    var sumTax = 0f
    while (round > 0) {
        var trade = liTrade[index]
        if(round < trade.stockAmount){
            split = Trade(stockId=stock.stockId, investIndex = trade.investIndex, stockAmount = trade.stockAmount - round,
                buyDate = trade.buyDate, buyPrice = trade.buyPrice, bonusId = trade.bonusId)
            trade.stockAmount = round
        }
        //平摊各项费用
        val ratio = trade.stockAmount.toFloat()/amount
        val tempCommission = (commission*100*ratio).roundToInt().toFloat()/100
        val tempTransfer = (transfer*100*ratio).roundToInt().toFloat()/100
        val tempTax = (tax*100*ratio).roundToInt().toFloat()/100

        trade.sellDate = date
        trade.sellPrice = price
        trade.commissionMoney += tempCommission
        trade.transferMoney += tempTransfer
        trade.taxMoney += tempTax

        trade.status = 9
        saveTrade.add(trade)

        sumCommission += tempCommission
        sumTransfer += tempTransfer
        sumTax += tempTax
        round -= trade.stockAmount
        index ++
    }

    //纠正平摊出现的误差
    val len = saveTrade.size
    if(commission != sumCommission){
        saveTrade[len-1].commissionMoney += (commission - sumCommission)
    }
    if(transfer != sumTransfer){
        saveTrade[len-1].transferMoney += (transfer - sumTransfer)
    }
    if(tax != sumTax){
        saveTrade[len-1].taxMoney += (tax - sumTax)
    }

    //设置提示线
    stock.buyLine = (price*90).toInt().toFloat()/100
    stock.sellLine = (price*115).toInt().toFloat()/100

    return Pair(split, saveTrade)
}

/**
 * 股票分红
 * @param tradeDao 购买记录的数据库访问类
 * @param stock 股票类
 * @param date 除权日期，时间戳（毫秒）
 * @param money 每股分红金额
 * @param amount 每股分股数量
 * @param holder 分红的股票持有数量
 *
 */
fun sysStockBonus(tradeDao: TradeDao, stock: Stock, date: Long, money: Float, amount: Float, holder: Int): Triple<Bonus, List<Trade>, Trade?>{
    var bonusTrade: Trade? = null
    var liTrade:MutableList<Trade> = arrayListOf()

    var bonus = Bonus(stockId=stock.stockId, bonusDate = date, bonusMoney = money*stock.holdStock, bonusAmount = (amount*stock.holdStock).toInt(), stockHold = stock.holdStock)

    if(money>0){
        liTrade = tradeDao.holdTrades(stockId = stock.stockId)

        var remain = holder
        for(trade in liTrade){
            if(remain<=0){
                break
            }
            trade.bonusMoney += money * trade.stockAmount
            remain -= trade.stockAmount
        }
    }
    if(amount>0){
        val stockBonusAmount = (amount*stock.holdStock).toInt()
        bonusTrade = Trade(stockId=stock.stockId, investIndex = stock.investIndex, stockAmount = stockBonusAmount,
            buyDate = date, buyPrice = 0f, commissionMoney = 0f, transferMoney = 0f)

        //stock.holdStock += stockBonusAmount
    }

    return Triple(bonus, liTrade, bonusTrade)
}

/**
 * 红利税补缴
 * @param bonusDao 分红记录的数据库访问类
 * @param trades 涉及补缴的股票购买记录
 */
fun sysBonusTax(bonusDao: BonusDao, trades: List<Trade>): List<Bonus>{
    var bonusIds: MutableList<Long> = mutableListOf()
    var bonusTaxs: MutableMap<Long, Float> = mutableMapOf()
    var saveBonus: List<Bonus> = mutableListOf()
    for(trade in trades){
        if(trade.bonusId>0){
            var faxRatio = bonusTaxRatio(trade.buyDate, trade.sellDate)
            if(faxRatio>0){
                val bonusTax = trade.bonusMoney * faxRatio
                trade.bonusTax = bonusTax
                bonusTaxs[trade.bonusId] = bonusTaxs[trade.bonusId]?:0 + bonusTax
                if(bonusIds.contains(trade.bonusId)){
                    bonusIds.add(trade.bonusId)
                }
            }
        }
    }
    if(bonusTaxs.isNotEmpty()){
        saveBonus = bonusDao.getBonusByIds(bonusIds)
        for(bonus in saveBonus) {
            bonus.taxMoney += (bonusTaxs[bonus.id]?:0f)
        }
    }
    return saveBonus
}

/**
 * 股票信息归零
 * 用于股票清仓后，股票数据的初始化
 * @param stock 股票类
 */
fun sysStockZero(stock: Stock){
    stock.costPrice = 0F
    stock.investMoney = 0F
    stock.holdStock = 0
    stock.investMoney = 0F
    stock.worthMoney = 0F
    stock.bonusMoney = 0F
    stock.commissionMoney = 0F
    stock.transferMoney = 0F
    stock.taxMoney = 0F
    stock.profitMoney = 0F
    stock.profitRatio = 0F

    stock.totalAmount = 0
    stock.totalInvest = 0f
    stock.maxAmount = 0
    stock.maxInvest = 0f
    stock.firstBuy = 0
    stock.sellLine = 0f
}

/**
 * 股票批次
 * 股票清仓后，转为投资批次，股票数据的初始化
 * @param stock 股票类
 * @param date 清仓（卖出）日期
 *
 */
fun sysStockBatch(stock: Stock, date: Long): Batch{
    var batch: Batch? = null
    batch = Batch(stockId = stock.stockId, investIndex=stock.investIndex,
        inDate = stock.firstBuy, outDate = date,
        maxAmount = stock.maxAmount, totalAmount = stock.totalAmount,
        maxInvest = stock.maxInvest, totalInvest = stock.totalInvest,
        profitMoney = stock.investProfit, bonusMoney = stock.bonusMoney,
        commissionMoney = stock.commissionMoney, transferMoney = stock.transferMoney,
        taxMoney = stock.taxMoney, bonusTax = stock.bonusTax
    )

    sysStockZero(stock)
    stock.totalProfit += stock.investProfit
    stock.status = 9
    return batch
}

/**
 * 计算红利税税率
 * 持股1个月以内20%，1个月至1年内10%，1年以上免
 * 1个月用30个自然日代替了
 * @param buyDate 股票买入日期
 * @param bonusDate 股票除权日期
 *
 */
private fun bonusTaxRatio(buyDate: Long, bonusDate: Long): Float{
    val days = (bonusDate - buyDate)/86400000
    var faxRatio = 0f
    if(days<30){
        faxRatio = 0.2f
    }else if(days<365){
        faxRatio = 0.1f
    }
    return faxRatio
}